package com.xbongbong.saas.model.impl;

import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.OutstockProductDao;
import com.xbongbong.saas.domain.entity.BusinessProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.util.StandardizeDataUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author Jian.Wang
 * @date  2019-01-28 9:11
 **/
@Service("OutstockProductModel")
public class OutstockProductModelImpl implements OutstockProductModel{

    @Resource
    private OutstockProductDao outstockProductDao;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private OutstockModel outstockModel;

    /**
     * 插入数据
     *
     * @param outstockProduct 入库单产品实体数据
     * @return 是否成功
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     **/
    @Override
    public Integer insert(OutstockProductEntity outstockProduct) {
        long now = DateTimeUtil.getInt();
        outstockProduct.setAddTime(now);
        outstockProduct.setUpdateTime(now);
        StandardizeDataUtil.standardizeNotString(outstockProduct);
        return outstockProductDao.insert(outstockProduct);
    }

    /**
     * 更新数据
     *
     * @param outstockProduct 入库单产品实体数据
     * @return 是否成功
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     **/
    @Override
    public Integer update(OutstockProductEntity outstockProduct) {
        long now = DateTimeUtil.getInt();
        outstockProduct.setUpdateTime(now);
        StandardizeDataUtil.standardizeNotString(outstockProduct);
        return outstockProductDao.update(outstockProduct);
    }

    @Override
    public Integer save(OutstockProductEntity outstockProduct) {
        Long id = outstockProduct.getId();
        if (id == null || id == 0L) {
            return insert(outstockProduct);
        }
        return update(outstockProduct);
    }

    /**
     * 根据主键删除记录
     *
     * @param key    主键
     * @param corpid 公司id
     * @return java.lang.Integer
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public Integer deleteByKey(Long key, String corpid) {
        return outstockProductDao.deleteByKey(key,corpid);
    }

    /**
     * 删除多条入库单下的所有产品
     *
     * @param corpid       公司ID
     * @param outstockIdIn 入库单Id集合
     * @return java.lang.Integer
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public Integer deleteByOutstockIdIn(String corpid, List<Long> outstockIdIn) {
        return outstockProductDao.deleteByOutstockIdIn(corpid,outstockIdIn);
    }

    /**
     * 删除入库单下的所有产品
     *
     * @param refId  id集合
     * @param corpid 公司id
     * @return java.lang.Integer
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public Integer deleteByOutstockId(Long refId, String corpid) {
        return outstockProductDao.deleteByOutstockId(refId, corpid);
    }

    /**
     * 获取一条入库单产品数据
     *
     * @param key    采购合同产品ID
     * @param corpid 公司id
     * @return OutstockProductEntity 一条数据实体
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public OutstockProductEntity getByKey(Long key, String corpid) {
        return outstockProductDao.getByKey(key, corpid);
    }

    /**
     * 多参数查询多条数据
     *
     * @param param 参数集合
     * @return List<OutstockProductEntity> 数据集合
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public List<OutstockProductEntity> findEntitys(Map<String, Object> param) {
        return outstockProductDao.findEntitys(param);
    }

    @Override
    public List<OutstockProductEntity> getProductsByOutstockIdIn(String corpid, List<Long> outstockIdIn) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.OUTSTOCK_ID_IN, outstockIdIn);
        param.put(ParameterConstant.DEL, 0);
        param.put(ParameterConstant.ORDER_BY_STR, StringConstant.SAAS_LINK_BUSINESS_ID);
        return outstockProductDao.findEntitys(param);
    }

    @Override
    public List<OutstockProductEntity> getProductsByOutstockIdAndType(String corpid, List<Long> outstockIdIn, Integer type) {
        if (CollectionsUtil.isEmpty(outstockIdIn)) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.OUTSTOCK_ID_IN, outstockIdIn);
        param.put(ParameterConstant.DEL, 0);
        param.put("type", type);
        return outstockProductDao.findEntitys(param);
    }

    @Override
    public List<OutstockProductEntity> getProductsByOutstockIdIn(String corpid, Long outstockId, List<Integer> delIn) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put("outWarehouseId", outstockId);
        param.put("delIn", delIn);
        param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        return outstockProductDao.findEntitys(param);
    }

    /**
     * 模糊查询
     *
     * @param corpid 参数集合
     * @param nameOrNoLike 模糊查询值
     * @return List<Long> 数据集合
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public List<Long> findOutstockIdsByRelaProNameOrNo(String corpid, String nameOrNoLike) {
        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("nameOrNoLike", nameOrNoLike);
        param.put("del", 0);
        return outstockProductDao.findOutstockIdsByRelaProNameOrNo(corpid,nameOrNoLike);
    }

    /**
     * 获取记录数
     *
     * @param param 参数集合
     * @return Integer Id集合
     * @author Jian.Wang
     * @date 2019/2/21 15:18
     */
    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return outstockProductDao.getEntitysCount(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }

    @Override
    public Double getProductNumSum(Map<String, Object> param) {
        return outstockProductDao.getProductNumSum(param);
    }

    @Override
    public Collection<OutstockProductEntity> mergeOutstockProduct(List<OutstockProductEntity> outstockProductList) {
        Map<Long, OutstockProductEntity> outstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OutstockProductEntity entity : outstockProductList) {
            Long productId = entity.getProductId();
            if (outstockProductMap.containsKey(productId)) {
                OutstockProductEntity mergeProduct = outstockProductMap.get(productId);
                Double mergeNum = Arith.add(mergeProduct.getProductNum(), entity.getProductNum());
                mergeProduct.setProductNum(mergeNum);
                outstockProductMap.put(productId, mergeProduct);
            } else {
                outstockProductMap.put(productId, entity);
            }
        }
        return outstockProductMap.values();
    }

    @Override
    public Map<Long, List<OutstockProductEntity>> getOutstockProductMap(List<OutstockProductEntity> updateWarehouseProducts) {
        Map<Long, List<OutstockProductEntity>> warehouseProduct = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (updateWarehouseProducts != null) {
            for (OutstockProductEntity outstockProduct : updateWarehouseProducts) {
                List<OutstockProductEntity> outstockProductList = new ArrayList<>();
                //仓库id
                Long warehouseId = outstockProduct.getWarehouseId();
                outstockProductList.add(outstockProduct);

                if (warehouseProduct.get(warehouseId) == null) {
                    warehouseProduct.put(warehouseId, outstockProductList);
                } else {
                    outstockProductList.addAll(warehouseProduct.get(warehouseId));
                    warehouseProduct.put(warehouseId, outstockProductList);
                }
            }
        }
        return warehouseProduct;
    }

    @Override
    public Integer deleteBatchById(Collection<Long> delOutstockProductIdList, String corpid, Integer del) {
        return outstockProductDao.deleteBatchById(delOutstockProductIdList,corpid, del);
    }

    @Override
    public void insertBatch(List<OutstockProductEntity> addOutstockProductEntityList) {
        StandardizeDataUtil.standardize4OutstockProductEntityList(addOutstockProductEntityList);
        outstockProductDao.insertBatch(addOutstockProductEntityList);
    }

    @Override
    public void updateOutBatch(List<OutstockProductEntity> updateBatchList, String corpid) {
        StandardizeDataUtil.standardize4OutstockProductEntityList(updateBatchList);
        outstockProductDao.updateOutBatch(updateBatchList,corpid);
    }

    @Override
    public void filterOutstockProduct(Map<Long, List<ContractProductEntity>> contractProductMap, String corpid, List<Long> dataIdList) throws XbbException {
        //TODO haibin.zhang 等我加完字段，这段代码就要死
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
        boolQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID),dataIdList));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,Arrays.asList(FieldTypeEnum.DATAID.getAlias(),OutstockEnum.getAttrConnectData(OutstockEnum.REF_ID)));
        if (paasFormDataEntityExtList.isEmpty()){
            return;
        }
        List<Long> instockIdList = new ArrayList<>();
        Map<Long,Long> idMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList){
            instockIdList.add(entityExt.getDataId());
            idMap.put(entityExt.getDataId(),entityExt.getData().getLong(OutstockEnum.REF_ID.getAttr()));
        }
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("outWarehouseIdIn",instockIdList);
        param.put("del",0);
        List<OutstockProductEntity> outstockProductEntityList = findEntitys(param);
        for (OutstockProductEntity entity : outstockProductEntityList){
            if (!idMap.containsKey(entity.getOutWarehouseId())){
                continue;
            }
            Long contractId = idMap.get(entity.getOutWarehouseId());
            List<ContractProductEntity> contractProductEntityList = contractProductMap.get(contractId);
            for (ContractProductEntity contractProductEntity : contractProductEntityList){
                if (Objects.equals(contractProductEntity.getProductId(),entity.getProductId())){
                    contractProductEntity.setProductNum(Arith.sub(contractProductEntity.getProductNum(),entity.getProductNum()));
                }
            }
        }
    }

    @Override
    public Map<Long, Double> contractUnOutstock(Set<Long> contractIdSet, String corpid) throws XbbException {
        Map<Long,Double> unOutstockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put("contractIdIn",contractIdSet);
        param.put("del",0);
        List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(param);
        for (ContractProductEntity entity : contractProductEntityList){
            Double num = unOutstockMap.getOrDefault(entity.getProductId(),0D);
            num = Arith.add(num,entity.getProductNum());
            unOutstockMap.put(entity.getProductId(),num);
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE),OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
        boolQueryBuilder.filter(termsQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID),contractIdSet));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK,boolQueryBuilder,PaasFormDataEntityExt.class,Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));
        if (paasFormDataEntityExtList.isEmpty()){
            return unOutstockMap;
        }
        List<Long> instockIdList = new ArrayList<>();
        for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList){
            instockIdList.add(entityExt.getDataId());
        }
        param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put("outWarehouseIdIn",instockIdList);
        param.put("del",0);
        List<OutstockProductEntity> outstockProductEntityList = findEntitys(param);
        for (OutstockProductEntity entity : outstockProductEntityList){
            if (!unOutstockMap.containsKey(entity.getProductId())){
                continue;
            }
            Double num = unOutstockMap.get(entity.getProductId());
            Double outNum = entity.getProductNum();
            unOutstockMap.put(entity.getProductId(),Arith.sub(num,outNum));
        }
        return unOutstockMap;
    }

    @Override
    public List<BusinessProductEntity> findProductNum(Map<String, Object> param) {
        return outstockProductDao.findProductNum(param);
    }

    @Override
    public Integer findProductNumCount(Map<String, Object> param) {
        return outstockProductDao.findProductNumCount(param);
    }

    @Override
    public Integer updateBatch(List<OutstockProductEntity> updateList, String corpid) throws XbbException {
        StandardizeDataUtil.standardize4OutstockProductEntityList(updateList);
        return outstockProductDao.updateBatch(updateList,corpid);
    }

    @Override
    public Long isProductSubAttrExist(String attr, String corpid, Long formId, Integer isArray) {
        return outstockProductDao.isProductSubAttrExist(attr,corpid,formId,isArray);
    }


    @Override
    public List<OutstockProductEntity> findForJob() {
        return outstockProductDao.findForJob();
    }

    @Override
    public Double summaryByAttr(String field,String corpid,  Long refId, List<Long> productIdIn){
        return outstockProductDao.summaryByAttr(field, corpid, refId, productIdIn);
    }

    @Override
    public Double summaryByAttrContractOutStock(String field,String corpid,  Long refId, List<Long> productIdIn){
        return outstockProductDao.summaryByAttrContractOutStock(field, corpid, refId, productIdIn);
    }

    @Override
    public Double summaryByAttrFromOutSide(String field,String corpid,  Long refId, List<Long> productIdIn){
        return outstockProductDao.summaryByAttrFromOutSide(field, corpid, refId, productIdIn);
    }

    @Override
    public Long countProductSub(String attr, String corpid, Long formId, Integer isArray) {
        return outstockProductDao.countProductSub(attr, corpid, formId, isArray);
    }

    @Override
    public List<OutstockProductEntity> getProductWithSubData(String attr, String corpid, Long formId, Integer isArray, Long idGte, Integer limit) {
        return outstockProductDao.getProductWithSubData(attr, corpid, formId, isArray, idGte, limit);
    }

    @Override
    public List<OutstockProductEntity> getUpStreamProduct(String corpid, Integer type, Long refId) throws XbbException {
        if (Objects.isNull(type) || Objects.isNull(refId)) {
            return null;
        }
        // 是否开启了工作流
        boolean isOpenWorkflow = commonHelp.isOpenWorkFlow(corpid);
        if (!isOpenWorkflow) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("refId", refId);
            param.put("type", type);
            param.put("del", 0);
            param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
            return findEntitys(param);
        } else {
            List<PaasFormDataEntityExt> outstockList = outstockModel.findOutstockList(corpid, type, refId,
                    Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()), Arrays.asList(FieldTypeEnum.DATAID.getAlias()));
            List<Long> outstockIdIn = new ArrayList<>();
            outstockList.forEach(item -> outstockIdIn.add(item.getDataId()));

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("refId", refId);
            param.put("type", type);
            param.put("del", 0);
            param.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
            param.put("outstockIdIn", outstockIdIn);
            return findEntitys(param);
        }
    }

    @Override
    public OutstockProductEntity getProductsByInstockIdAndRefProductId(Long outstockId, Long refProductId, String corpid) {
        return outstockProductDao.getProductsByInstockIdAndRefProductId(outstockId, refProductId, corpid);
    }

    @Override
    public Integer dataConsistencyUpdate(String corpid, Long productId, String productName, String specification, String productNo) {
        return outstockProductDao.dataConsistencyUpdate(corpid, productId, productName, specification, productNo);
    }

    @Override
    public Integer updateMulti(List<OutstockProductEntity> list, String corpid) {
        StandardizeDataUtil.standardize4OutstockProductEntityList(list);
        return outstockProductDao.updateMulti(list, corpid);
    }

    @Override
    public void updateOutstockProductById(List <OutstockProductEntity> outstockProductEntityList, String corpid){
        StandardizeDataUtil.standardize4OutstockProductEntityList(outstockProductEntityList);
        outstockProductDao.updateOutstockProductById(outstockProductEntityList, corpid);
    }

    @Override
    public List<OutstockProductEntity> getOutstockProductById(List<Long> outstockProductId, String corpid){
        return outstockProductDao.getOutstockProductById(outstockProductId, corpid);
    }

    @Override
    public List<OutstockProductEntity> getOutstockProductByRefId(List<Long> refId, String corpid){
        return outstockProductDao.getOutstockProductByRefId(refId, corpid);
    }

    @Override
    public List<OutstockProductEntity> getOrderOutStockData(Long dataId, String corpid) {
        return outstockProductDao.getOrderOutStockData(dataId, corpid);
    }

    @Override
    public OutstockProductEntity getOutstockProductSum(Map<String, Object> map) {
        return outstockProductDao.getOutstockProductSum(map);
    }

    @Override
    public Set<Long> getWarehouseIdUnion(Set<Long> warehouseIdList, String corpid) {
        return outstockProductDao.getWarehouseIdUnion(warehouseIdList, corpid);
    }
}
